package com.lzy.model;

import lombok.*;
import org.apache.commons.lang.ArrayUtils;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 内容检测结果返回
 *
 * @author lzy
 */
@lombok.Data
@ToString
@EqualsAndHashCode
public class AliyunContentScanResult {

    /**
     * 错误码，和HTTP的status code一致。 200 请求正常
     */
    public Integer code;
    /**
     * 请求返回数据
     */
    private Data[] data;

    /**
     * 接口是否成功
     * @return
     */
    public boolean isSuccess() {
        return Integer.valueOf(200).equals(200);
    }

    private static final LabelEnum[] FILTER_LABEL = {LabelEnum.politics, LabelEnum.terrorism, LabelEnum.abuse, LabelEnum.porn, LabelEnum.contraband};

    /**
     * 获取敏感词信息
     * @return
     */
    public List<ScanResult> getScanResult() {
        return getScanResult(FILTER_LABEL);
    }

    public List<ScanResult> getScanResult(LabelEnum... enums) {
        if (data == null) {
            return null;
        }
        return Stream.of(data)
                .filter(Objects::nonNull)
                .filter(o -> o.getResults() != null)
                .flatMap(o -> Stream.of(o.getResults()))
                .filter(o -> !SuggestionEnum.pass.toString().equals(o.getSuggestion()))
                .filter(o -> ArrayUtils.contains(enums, LabelEnum.valueOf(o.getLabel())))
                .flatMap(o -> Stream.of(Optional.ofNullable(o.getDetails()).orElse(new Detail[]{}))
                        .filter(j -> ArrayUtils.contains(enums, LabelEnum.valueOf(j.getLabel())))
                        .map(j -> ScanResult.builder()
                                .label(LabelEnum.valueOf(j.getLabel()))
                                .content(Stream.of(Optional.ofNullable(j.getContexts()).orElse(new Context[]{}))
                                        .map(Context::getContext).collect(Collectors.joining(",")))
                                .build())).collect(Collectors.toList());
    }

    /**
     * 文本是否正常
     * @return
     */
    public boolean isPass() {
        if (data == null) {
            return false;
        }
        return Stream.of(data)
                .filter(Objects::nonNull)
                .filter(o -> o.getResults() != null)
                .flatMap(o -> Stream.of(o.getResults()))
                .noneMatch(o -> ArrayUtils.contains(FILTER_LABEL, LabelEnum.valueOf(o.getLabel())));

    }


    /**
     * 请求返回数据
     */
    @lombok.Data
    @ToString
    @EqualsAndHashCode
    public static class Data {
        /**
         * 错误码，和HTTP的status code一致。 200 请求正常
         */
        private Integer code;
        /**
         * 错误描述信息。code=200时 msg=ok
         */
        private String msg;
        /**
         * 检测对象对应的数据ID。
         */
        private String dataId;
        /**
         * 本次检测任务的ID。
         */
        private String taskId;
        /**
         * 如果被检测文本命中了自定义关键词词库中的关键词，则会返回当前字段，并将命中的关键词替换为星号（*）。
         */
        private String filteredContent;
        /**
         * 返回结果。调用成功时（code=200），返回结果中包含一个或多个元素。每个元素是个结构体，具体结构描述请参见result。
         */
        private Result[] results;
    }

    /**
     * 检测结果
     */
    @lombok.Data
    @ToString
    @EqualsAndHashCode
    public static class Result {
        /**
         * 检测场景，和调用请求中的场景对应。
         */
        private String scene;
        /**
         * 建议您执行的后续操作。取值：
         * pass：文本正常，可以直接放行
         * review：文本需要进一步人工审核
         * block：文本违规，可以直接删除或者限制公开
         */
        private String suggestion;

        /**
         * 文本垃圾检测结果的分类。取值：
         * normal：正常文本
         * spam：含垃圾信息
         * ad：广告
         * politics：涉政
         * terrorism：暴恐
         * abuse：辱骂
         * porn：色情
         * flood：灌水
         * contraband：违禁
         * meaningless：无意义
         * customized：自定义（例如命中自定义关键词）
         */
        public String label;
        /**
         * 结果属于当前分类的概率，取值范围：0.00~100.00。值越高，表示越有可能属于当前分类。
         */
        private Double rate;
        /**
         * 命中风险的详细信息，一条文本可能命中多条风险详情。具体结构描述请参见
         */
        private Detail[] details;
    }

    /**
     * 命中风险的详细信息
     */
    @lombok.Data
    @ToString
    @EqualsAndHashCode
    public static class Detail {
        /**
         * 文本垃圾检测结果的分类。取值：
         * normal：正常文本
         * spam：含垃圾信息
         * ad：广告
         * politics：涉政
         * terrorism：暴恐
         * abuse：辱骂
         * porn：色情
         * flood：灌水
         * contraband：违禁
         * meaningless：无意义
         * customized：自定义（例如命中自定义关键词）
         */
        private String label;

        private Context[] contexts;

        private HintWord[] hintWords;
    }

    @lombok.Data
    @ToString
    @EqualsAndHashCode
    public static class Context {
        /**
         * 检测文本命中的风险内容的上下文信息。如果命中了您自定义的风险文本库，则会返回命中的文本内容（关键词或相似文本
         */
        private String context;
        /**
         * 命中自定义词库时，才会返回当前字段。取值为创建词库时设置的词库名称。
         */
        private String libName;
        /**
         * 命中您自定义文本库时，才会返回当前字段。取值为创建风险文本库后系统返回的文本库code。
         */
        private String libCode;
        /**
         * 命中行为规则时，才会返回当前字段。取值：
         * user_id
         * ip
         * umid
         * content
         * similar_content
         * imei
         * imsi
         */
        private String ruleType;
    }

    @lombok.Data
    @ToString
    @EqualsAndHashCode
    public static class HintWord {
        /**
         * 文本命中的系统关键词内容。
         */
        private String context;
    }

    /**
     * 检测结果
     */
    @lombok.Data
    @ToString
    @EqualsAndHashCode
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class ScanResult {
        /**
         * 违规文本
         */
        private String content;
        /**
         * 违规标签
         */
        private LabelEnum label;
    }

    public static enum SuggestionEnum {
        /**
         * 文本正常，可以直接放行
         */
        pass("正常"),
        /**
         * 文本需要进一步人工审核
         */
        review("人工审核"),
        /**
         * 文本违规，可以直接删除或者限制公开
         */
        block("文本违规");
        private String text;

        SuggestionEnum(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }
    }

    public static enum LabelEnum {
        /**
         * 正常文本
         */
        normal("正常文本"),
        /**
         * 含垃圾信息
         */
        spam("含垃圾信息"),
        /**
         * 广告
         */
        ad("广告"),
        /**
         * 涉政
         */
        politics("涉政"),
        /**
         * 暴恐
         */
        terrorism("暴恐"),
        /**
         * 辱骂
         */
        abuse("辱骂"),
        /**
         * 色情
         */
        porn("色情"),
        /**
         * 灌水
         */
        flood("灌水"),
        /**
         * 违禁
         */
        contraband("违禁"),
        /**
         * 无意义
         */
        meaningless("无意义"),
        /**
         * 自定义（例如命中自定义关键词)
         */
        customized("自定义"),
        ;
        private String text;

        LabelEnum(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }
    }
}


